#!/usr/bin/env python

##########################################################################
# File Name: utils.py
# Author: baohua
# Mail: liubaohuachina@163.com
# Create Time: 2020/03/24 09:21:43
# Version: 1.0
# Description: 
##########################################################################

import copy
import datetime
import functools
import json
import random
import string
import time


class CodingError(Exception):
    pass


# 时间戳10位，精确到秒
def timestamp():
    return int(time.time())


# 生成订单号
def create_out_trade_no():
    time = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
    return time + random_number(6)


def random_string(length=25):
    return ''.join([random.choice(
        string.ascii_lowercase + string.digits) for x in range(length)])


def random_number(length=25):
    return ''.join([random.choice(string.digits) for x in range(length)])


def datetime_str():
    # 用now而不是utcnow省去了再转换，本应用也很少可能扩展到别的时区
    # return datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')
    return datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')


def cn_datetime_str():
    "没有秒钟"
    return datetime.datetime.now().strftime('%Y年%-m月%-d日 %H点%M分')


def cn_date_str():
    "只有日期，没有时间"
    return datetime.datetime.now().strftime('%Y年%-m月%-d日')


def split2ids(oname):
    """Decorate methods to return a list of id's."""
    def decorator(method):
        @functools.wraps(method)
        def wrapper(self, *args, **kwargs):
            if hasattr(self, oname) and type(self.__getattribute__(oname)) in [type(""), type(u"")]:
                ids = []
                if self.__getattribute__(oname):
                    try:
                        ids = [int(a) for a in self.__getattribute__(oname).split(',')]
                    except ValueError:
                        pass
                return ids
            else:
                raise CodingError
        return wrapper
    return decorator


def ijson(oname):
    """Decorate methods to return info as json dict."""
    def decorator(method):
        @functools.wraps(method)
        def wrapper(self, *args, **kwargs):
            print(type(self.__getattribute__(oname)))
            if hasattr(self, oname) and type(self.__getattribute__(oname)) in [type(""), type(u"")]:
                try:
                    j = json.loads(self.__getattribute__(oname))
                except ValueError:
                    return {}
                return j
            else:
                raise CodingError
        return wrapper
    return decorator


def to_cn_date(oname):
    """Decorate methods to return date in chinese format"""
    def decorator(method):
        @functools.wraps(method)
        def wrapper(self, *args, **kwargs):
            if hasattr(self, oname) and type(self.__getattribute__(oname)) == datetime.datetime:
                return self.__getattribute__(oname).strftime("%Y年%m月%d日")
            else:
                return ""
        return wrapper
    return decorator


class GetInfoMixin(object):
    def ginfo(self, info_name):
        """self.info必须在存在
        """
        i = self.get_argument(info_name, None)
        if i:
            self.info[info_name] = i


def sa_r2d(row):
    """只适用于单个表整行
    """
    d = {}
    if not row:
        return d

    for column in row.__table__.columns:
        v = getattr(row, column.name)
        if type(v) == datetime.datetime:
            v = v.strftime('%Y-%m-%d %H:%M:%S')
        elif type(v) == datetime.date:
            v = v.strftime('%Y-%m-%d')
        d[column.name] = v
    return d


def sa_t2d(row):
    """适用于多个表分字段
    """
    d = {}
    if not row:
        return d

    for key in row.keys():
        v = getattr(row, key)
        if type(v) == datetime.datetime:
            v = v.strftime('%Y-%m-%d %H:%M:%S')
        elif type(v) == datetime.date:
            v = v.strftime('%Y-%m-%d')
        d[key] = v
    return d


def sa_rs2ds(rows):
    a = []
    if not rows:
        return a

    for row in rows:
        a.append(sa_r2d(row))
    return a


def sa_ts2ds(rows):
    a = []
    if not rows:
        return a

    for row in rows:
        a.append(sa_t2d(row))
    return a


# 和sa_rs2ds相似，但返回dict
def sa_rs2dd(rows):
    a = {}
    if not rows:
        return a

    for row in rows:
        a[row.id] = sa_r2d(row)
    return a


# 和ta_rs2ds相似，但返回dict
def sa_ts2dd(rows):
    a = {}
    if not rows:
        return a

    for row in rows:
        a[row.id] = sa_t2d(row)
    return a


# convert '2014-04-05 12:03:45' to datetime
def isoparse(s):
    try:
        return datetime.datetime(
            int(s[0:4]), int(s[5:7]), int(s[8:10]),
            int(s[11:13]), int(s[14:16]), int(s[17:19]))
    except:
        return None


# convert '2014-04' to datetime
def dateparse(s):
    try:
        return datetime.datetime(int(s[0:4]), int(s[5:7]), 1, 1, 1, 1)
    except:
        return None


class MetaEnumType(type):
    def __new__(cls, name, bases, attrs):
        newattrs = {}
        if 'types' in attrs and isinstance(attrs['types'], list):
            i = 0
            for t in attrs['types']:
                if isinstance(t, str):
                    newattrs[t] = i
                    i += 1

        return type.__new__(cls, name, bases, newattrs)


# 直接产生一个object
class EnumType(object):
    def __init__(self, *tps):
        i = 0
        for tp in tps:
            self.__dict__[tp] = i
            i += 1


class DummyObj(object):
    """ 一个假object，任何attr都会返回空字符串，如：
    o = DummyOjb()
    o.hello # 返回 ''
    """
    def __getattribute__(self, name):
        return ""


class CopyObj(object):
    """ 一个object的拷贝，除object原有的attr外, 任何attr都会返回空字符串，如：
    o 本来有hello, 但没有world
    oo = CopyOjb(o)
    oo.hello # 返回 o.hello
    oo.world # 返回 ''
    """

    def __init__(self, obj=None):
        if not obj:
            self = object()
        else:
            self = copy.copy(obj)  # 有必要用deepcopy吗？

    def __getattribute__(self, name):
        try:
            return object.__getattribute__(self, name)
        except AttributeError:
            return ""


def response(code='000000', desc='ok', data=''):
    result = {'code': code, 'desc': desc}
    if data:
        result['data'] = data
    return result